<div id="demo">
    <p>Step 1. <button type="button" id="attach" tabindex="1">subscribe</button> to the <code>arrow</code> event.<br>
    <input type="checkbox" id="delegate" value="1" tabindex="1">
        <label for="delegate">Use a delegated subscription</label></p>
    <p>Step 2. Click on a toaster-bot and move it around with the arrow keys.</p>

    <div id="homebase">
        <img id="A" class="robot" tabindex="3" src="{{{componentAssets}}}/toast-8b-left.png" />
        <img id="B" class="robot" tabindex="3" src="{{{componentAssets}}}/toast-8b-right.png" />
    </div>

    <button type="button" id="detach" tabindex="4">Detach subscriptions</button>
</div>

<script>
YUI({ filter: 'raw' }).use('node', 'event-synthetic', 'transition', function (Y) {
    Y.Event.define("arrow", {
        // Webkit and IE repeat keydown when you hold down arrow keys.
        // Opera links keypress to page scroll; others keydown.
        // Firefox prevents page scroll via preventDefault() on either
        // keydown or keypress.
        _event: (Y.UA.webkit || Y.UA.ie) ? 'keydown' : 'keypress',

        _keys: {
            '37': 'left',
            '38': 'up',
            '39': 'right',
            '40': 'down'
        },

        _keyHandler: function (e, notifier) {
            if (this._keys[e.keyCode]) {
                e.direction = this._keys[e.keyCode];
                notifier.fire(e);
            }
        },

        on: function (node, sub, notifier) {
            sub._detacher = node.on(this._event, this._keyHandler,
                                    this, notifier);
        },

        detach: function (node, sub, notifier) {
            sub._detacher.detach();
        },

        delegate: function (node, sub, notifier, filter) {
            sub._delegateDetacher = node.delegate(this._event, this._keyHandler,
                                                  filter, this, notifier);
        },

        detachDelegate: function (node, sub, notifier) {
            sub._delegateDetacher.detach();
        }
    });


    var robotA = Y.one('#A'),
        robotB = Y.one('#B'),
        subs,
        moving = false;

    robotA.setData('x', parseInt(robotA.getStyle('left'), 10));
    robotA.setData('y', parseInt(robotA.getStyle('top'), 10));
    robotB.setData('x', parseInt(robotB.getStyle('left'), 10));
    robotB.setData('y', parseInt(robotB.getStyle('top'), 10));

    // create variables for image path/filenames
    // Use 8bit pngs for IE
    var imgBits = (Y.UA.ie && Y.UA.ie < 9) ? '-8b-' : '-24b-',
        imgNamePre = '{{{componentAssets}}}/toast' + imgBits,

        imgUp = imgNamePre + 'up.png',
        imgDown = imgNamePre + 'down.png',
        imgLeft = imgNamePre + 'left.png',
        imgRight = imgNamePre + 'right.png';

    Y.one('#A').setAttribute('src', imgLeft);
    Y.one('#B').setAttribute('src', imgRight);

    function move(e) {
        // to prevent page scrolling
        e.preventDefault();
        if(moving){
            return; // Don't move during a transition (a move)
        }else{
            moving = true; // During moving, block other arrow keys from moving
        }

        var xy = this.getData(),
            imgWidth,
            imgHeight,
            // var scale is used to make the image size and distance moved
            // proportional to the Y position of the image
            scale = (150 + xy.y) / 150,
            moveXDistance = 40,
            moveYDistance = 20;

        switch (e.direction) {
            case 'up':
                if(xy.y < -100){
                    moving = false;
                    return; // Stop moving when image gets too small
                }
                xy.y -= Math.round(moveYDistance * scale);
                e.target.setAttribute('src', imgUp);
                break;
            case 'down':
                if(xy.y > 90){
                    moving = false;
                    return; // Stop moving when image gets too big
                }
                xy.y += Math.round(moveYDistance * scale);
                e.target.setAttribute('src', imgDown);
                break;
            case 'left':
                xy.x -= Math.round(moveXDistance * scale);
                e.target.setAttribute('src', imgLeft);
                break;
            case 'right':
                xy.x += Math.round(moveXDistance * scale);
                e.target.setAttribute('src', imgRight);
                break;
        }
        scale = 150 / (150 - xy.y); // calculate scale with new Y dimentions
        imgWidth = Math.round(scale * 180) + 'px';
        imgHeight = Math.round(scale * 210) + 'px';
        this.transition({
            top : (xy.y + 'px'),
            left: (xy.x + 'px'),
            width: imgWidth,
            height: imgHeight,
            duration: .8
        }, function(){
            moving = false; // now that move is done, allow arrow keys to move again
        });

        this.setData('x', xy.x);
        this.setData('y', xy.y);
    }

    function detachSubs() {
        if (subs) {
            subs.detach();
            subs = null;
            Y.all('.robot').removeClass('yui3-focused');
        }
    }

    Y.one("#attach").on("click", function (e) {
        detachSubs();

        if (Y.one("#delegate").get('checked')) {
            subs = Y.one('#demo').delegate('arrow', move, '.robot');
        } else {
            subs = new Y.EventHandle([
                robotA.on("arrow", move),
                robotB.on("arrow", move)
            ]);
        }
    });

    Y.one("#detach").on("click", detachSubs);
    Y.all('.robot').on('focus', function(e){
        if (subs) {
            Y.all('.robot').removeClass('yui3-focused');
            e.target.addClass('yui3-focused');
        }
    });

    Y.all('.robot').on('click', function(e){
        e.target.focus();
    });

});
</script>
